package com.ttbj.move_rule.service.impl;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.ttbj.move_rule.dao.BillDistanceMapper;
import com.ttbj.move_rule.dao.BillServeMapper;
import com.ttbj.move_rule.dao.BillVehicleMapper;
import com.ttbj.move_rule.po.BillDistance;
import com.ttbj.move_rule.po.BillServe;
import com.ttbj.move_rule.po.BillVehicle;
import com.ttbj.move_rule.service.MoveBillStrategy;
import com.ttbj.product.api.DriverFacade;
import com.ttbj.product.api.LocationFacade;
import com.ttbj.product.bean.dto.CoordDto;
import com.ttbj.product.bean.dto.Distance;
import com.ttbj.util.Assert;
import com.zywl.common.utils.DateUtils;

/**
 * 阶梯式的距离计费方式
 * 1.起步 - 超出起步 - 超出长途
 * 2分白天黑夜的区别计费
 * @author Administrator
 *
 */
@Component
public class DisMoveBillStrategy implements MoveBillStrategy {

	@Autowired
	LocationFacade locationFacade = null;

	@Autowired
	BillDistanceMapper billDistanceMapper = null;

	@Autowired
	DriverFacade driverFacade = null;

	@Override
	public Float strategyInterface(Integer billType, String senderLat, String senderLng, String reciverLat, String reciverLng, Integer floorNum, Integer pieceNum, Integer baleNum, String truckType, Integer serciveLevel, Integer orderDriverRequire) throws Exception {
		Float disance = getDisance(senderLat, senderLng, reciverLat, reciverLng);
		List<BillDistance> ruleList = billDistanceMapper.getRuleList();
		List<BillDistance> rule = getRule(ruleList);
		BillDistance distanceRule = rule.get(0);
		Float fee = getFee(disance, distanceRule);
		return fee * orderDriverRequire;
	}

	/**
	 * 获取距离
	 * 
	 * @param senderLat
	 * @param senderLng
	 * @param reciverLat
	 * @param reciverLng
	 * @throws Exception
	 */
	private Float getDisance(String senderLat, String senderLng, String reciverLat, String reciverLng) throws Exception {
		Distance distance = locationFacade.getDistance(new CoordDto(senderLng, senderLat), new CoordDto(reciverLng, reciverLat));
		return distance.getKilometer();
	}

	/**
	 * 当前小时数大于夜晚开始时间小于白天开始时间 当前时间大于夜晚开始时间
	 * 
	 * @param rules
	 * @return
	 */
	private List<BillDistance> getRule(List<BillDistance> rules) {
		int hour = DateUtils.getHour();
		if (Assert.isEmpty(rules)) {
			return null;
		}
		Integer day = null;
		Integer night = null;
		for (BillDistance distanceRule : rules) {
			if (distanceRule.getDistanceId() == 1) {
				day = distanceRule.getDistanceDay();
			} else {
				night = distanceRule.getDistanceDay();
			}
		}
		Stream<BillDistance> stream = rules.stream();
		if (hour >= night || hour < day) {
			return stream.filter(rule -> rule.getDistanceId() == 2).collect(Collectors.toList());
		}
		return stream.filter(rule -> rule.getDistanceId() == 1).collect(Collectors.toList());
	}

	/**
	 * 未加权重的费用
	 * 
	 * @param disance
	 * @param distanceRule
	 * @return
	 */
	private Float getFee(Float disance, BillDistance distanceRule) {
		Float fee = null;
		//隶属于哪种距离起步还是长途
		Integer billFlag = disance > distanceRule.getDistanceLong() ? 3 : (disance > distanceRule.getDistanceStartMileage() ? 2 : 1);
		switch (billFlag) {
		case 1:
			fee = getOne(disance, distanceRule);
			break;
		case 2:
			fee = getTwo(disance, distanceRule);
			break;
		case 3:
			fee = getThree(disance, distanceRule);
			break;
		default:
			fee = 0f;
			break;
		}
		return fee;
	}



	private Float getOne(Float disance, BillDistance distanceRule) { // 起步价
		return distanceRule.getDistanceStartPrice();
	}

	private Float getTwo(Float disance, BillDistance distanceRule) { // 超出起步价
		Float one = getOne(disance, distanceRule);
		Float subKile = disance - distanceRule.getDistanceStartMileage();
		return one + subKile * distanceRule.getDistanceBeyondPrice();
	}

	private Float getThree(Float disance, BillDistance distanceRule) { // 超出长途价
		Float one = getOne(disance, distanceRule);
		Float two = getTwo(disance, distanceRule);
		Float subKile = disance - distanceRule.getDistanceLong();
		return one + two + subKile * distanceRule.getDistanceLongPrice();
	}
}
